﻿using AutoCommunication.Enums;
using AutoCommunication.Helper;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace AutoCommunication.Base
{
    /// <summary>
    /// DeviceBase基类
    /// </summary>
    public abstract class BaseDevice<Tvariable> : IDevice2 where Tvariable : BaseVariable
    {
        #region Fields

        /// <summary>
        /// 线程锁
        /// </summary>
        [Browsable(false), JsonIgnore]
        protected static readonly object Readlock = new object();

        /// <summary>
        /// 连接后,是否自动关闭连接
        /// </summary>
        protected bool isAutoOpen = true;

        /// <summary>
        /// 断开连接总次数:每执行一次重连,这个数就会被增加一次
        /// <para>用于判断读取是否稳定</para>
        /// </summary>
        private int DisConnectCount = 0;

        /// <summary>
        /// 每读取失败一次会+1;达到MaxErrorCount次数后,将connected设置为false,判断为掉线了,然后执行重连
        /// </summary>
        private int ErrorCount = 0;

        private bool IsGrouped = false;
        /// <summary>
        /// 在一次重连程序中,执行的次数(只要没重连成功,这个就一直增加);再次掉线,会重新统计
        /// <para>用于判断重连是否顺畅</para>
        /// </summary>
        private int ReConnectCount = 0;

        #endregion Fields

        #region Events

        [Browsable(false)]
        public event Action<BaseVariable, AlarmEventArgs> Alarmer;

        [Browsable(false)]
        public event Action<BaseVariable> DataChange;

        [Browsable(false)]
        public event Action<string, bool> EventConnect;

        [Browsable(false)]
        public event Action<string> EventDisConnect;

        #endregion Events

        #region Properties

        /// <summary>
        /// 此设备的所有变量集合
        /// </summary>
        [JsonProperty("变量集合"), DisplayName("变量集合"), Category("设备信息")]
        public List<Tvariable> AllVarable { get; set; } = new List<Tvariable>() { };

        /// <inheritdoc/>
        /// <summary>
        /// 暂时没有启用这个集合,方便以后wpf等绑定可能需要
        /// </summary>
        [Browsable(false), JsonIgnore]
        public Dictionary<string, Tvariable> AllVarableDictionary { get; set; } = new Dictionary<string, Tvariable>();

        [JsonProperty("缓冲区大小"), DisplayName("缓冲区大小"), Category("系统默认参数")]
        public int BufferSize { get; set; } = 4096;

        [JsonIgnore, Browsable(false)]
        public virtual bool Connected { get; set; } = false;

        /// <summary>
        /// 用于取消线程
        /// </summary>
        [JsonIgnore, Browsable(false)]
        public CancellationTokenSource Cts { get; set; } = new CancellationTokenSource();
        [JsonIgnore, Browsable(false)]
        public double? CycleTime { get; set; } = 0;

        [JsonProperty("描述"), DisplayName("描述"), Category("设备信息")]
        public string Description { get; set; } = $"描述这是一个什么样的的设备........";

        [JsonProperty("使用采用快速读取"), DisplayName("使用采用快速读取"), Category("系统默认参数")]
        public bool FastRead { get; set; } = true;

        [JsonProperty("字节格式(大小端)"), DisplayName("字节格式(大小端)"), Category("设备信息")]
        public abstract EndianFormat Format { get; set; }

        /// <summary>
        /// 通讯组:通常由此设备的Group()方法初始化
        /// </summary>
        [JsonIgnore, Browsable(false)]
        public List<Group<Tvariable>> GroupList { get; set; } = new List<Group<Tvariable>>() { };

        [JsonProperty("是否激活"), DisplayName("是否激活"), Category("设备信息")]
        public bool IsActive { get; set; } = true;

        [JsonIgnore, Browsable(false)]
        public bool IsFirstConnect { get; set; } = true;

        [JsonIgnore, Browsable(false)]
        public bool IsReady { get; set; } = false;

        [JsonIgnore, Browsable(false)]
        public bool IsRuning { get; set; } = false;

        [Browsable(false), JsonIgnore]
        public LoggerDelegate Loger { get; set; }

        [JsonIgnore, Browsable(false)]
        public int MaxErrorCount { get; set; } = 2;

        [JsonProperty("一次报文最多读取多少个位"), DisplayName("一次报文最多读取多少个位"), Category("系统默认参数")]
        public int MaxReadBits { get; set; } = 1900;

        [JsonProperty("一次报文最多读取多少个字节"), DisplayName("一次报文最多读取多少个字节"), Category("系统默认参数")]
        public int MaxReadBytes { get; set; } = 120;

        /// <inheritdoc/>
        /// <inheritdoc/>
        public abstract string Name { get; set; }

        [JsonIgnore, Browsable(false)]
        public int ReconnectionCount { get; set; } = 0;

        [JsonIgnore, Browsable(false)]
        public int ReConnectTime { get; set; } = 1000;

        [JsonProperty("连接超时时间"), DisplayName("连接超时时间"), Category("设备信息"), Description("多久连接不上,就报异常,单位毫秒")]
        public int Timeout { get; set; } = 1500;

        [JsonProperty("变量名形式"), DisplayName("变量名形式"), Category("变量名形式")]
        public VariableNameType VariableNameType { get; set; } = VariableNameType.DevNameAndVarName;

        #endregion Properties

        #region Indexers

        /// <summary>
        /// 根据变量名或者变量地址获取变量的值
        /// </summary>
        /// <param name="VarNameOrAddress">变量名或者变量地址</param>
        /// <returns></returns>
        public object this[string VarNameOrAddress]
        {
            get
            {
                var res1 = AllVarable.FindAll(x => x.Name.Norm() == VarNameOrAddress.Norm());
                var res2 = AllVarable.FindAll(x => x.Address.Norm() == VarNameOrAddress.Norm());
                if (res1.Any())
                {
                    return res1[0].Value;
                }
                else if (res2.Any())
                {
                    return res2[0].Value;
                }
                else
                {
                    return "未找到变量,请确认变量是否存在";
                }
            }
            set
            {
                //TODO 写入值的方法
            }
        }

        #endregion Indexers

        #region Public Methods

        /// <summary>
        /// 安全的断开设备,推荐使用
        /// </summary>
        /// <returns></returns>
        public Result Close()
        {
            isAutoOpen = true;
            return Disconnect();
        }

        public Result Init1()
        {
            Result result = new Result();
            Encoding.RegisterProvider(CodePagesEncodingProvider.Instance);
            _ = result.SetErrInfo(CheckDeviceParameters()).IsSucceed &&
                result.SetErrInfo(CheckParameters()).IsSucceed &&
                result.SetErrInfo(CheckOther()).IsSucceed;
            if (result.IsSucceed)
            {
                IsReady = true;
            }
            return result;
        }

        /// <summary>
        /// 初始化设备,为调用连接设备的方法,确认能否连接
        /// </summary>
        /// <returns></returns>
        public Result Init2()
        {
            Result result = new Result();
            _ = result.SetErrInfo(Init1()).IsSucceed &&
                 result.SetErrInfo(AddToAuto()).IsSucceed;
            return result;
        }

        /// <summary>
        /// 安全的连接设备,推荐使用
        /// </summary>
        /// <returns></returns>
        public Result Open()
        {
            isAutoOpen = false;
            return Connect();
        }

        public Result<Tvariable> Read(Tvariable tvariable)
        {
            Result<Tvariable> result = new Result<Tvariable>();
            result.Value = tvariable;
            List<Tvariable> list = new List<Tvariable>();
            list.Add(tvariable);
            result.SetErrInfo(Read(list));
            return result;
        }

        public Result<List<Tvariable>> Read(List<Tvariable> tvariables)
        {
            Result<List<Tvariable>> result = new Result<List<Tvariable>>();
            var groups = Group(tvariables);
            result.Value = tvariables;
            foreach (var group in groups)
            {
                result.SetErrInfo(Read(group));
            }
            return result;
        }

        /// <summary>
        /// 非常重要的方法:读取并解析一个变量组
        /// </summary>
        /// <param name="group"></param>
        /// <returns></returns>
        public virtual Result<Group<Tvariable>> Read(Group<Tvariable> group)
        {
            var result = new Result<Group<Tvariable>>();
            if (isAutoOpen)
            {
                Connect();
            }
            try
            {
                //发送命令并获取响应报文
                byte[] Response = null;
                byte[] ResponseData = null;
                foreach (var Requst in group.Requst)
                {
                    var sendResult = SendAndRevice(Requst);
                    if (!sendResult.IsSucceed)
                    {
                        return result.SetErrInfo(sendResult).EndTime();
                    }
                    if (!sendResult.Value.Any())
                    {
                        result.IsSucceed = false;
                        result.Err = "响应结果为空";
                        return result.EndTime();
                    }
                    if (Response == null) Response = sendResult.Value;
                    else Response = Response.Concat(sendResult.Value).ToArray();
                    if (ResponseData == null) ResponseData = sendResult.ResponseData;
                    else ResponseData = ResponseData.Concat(sendResult.ResponseData).ToArray();

                    // group.Response = sendResult.Value;
                    //  group.ResponseData = sendResult.ResponseData;
                    //var str = Encoding.GetEncoding("GBK").GetString(sendResult.ResponseData);
                    //var str2 = Encoding.Unicode.GetString(sendResult.ResponseData);
                    //var str3 = Encoding.UTF8.GetString(sendResult.ResponseData);
                    //var str4 = Encoding.ASCII.GetString(sendResult.ResponseData);
                    //var str5 = Encoding.Default .GetString(sendResult.ResponseData);
                }
                group.Response = Response;
                group.ResponseData = ResponseData;
                return Common.DataAnalysis(group, group.ResponseData, Format, DataChange, Alarmer).SetErrInfo(result).EndTime();
            }
            catch (Exception ex)
            {
                result.IsSucceed = false;
                result.Err = ex.Message;
            }
            finally
            {
                if (isAutoOpen) Disconnect();
            }
            return result.EndTime();
        }

        public virtual Result<string> ReadAsync(string name)
        {
            Result<string> result = new Result<string>();
            var res = AllVarable.Where(x => x.Name.Norm() == name.Norm()).ToList();
            if (res.Any())
            {
                var varable = res.First();
                result.Value = varable.Value.ToString();
                // var gp = Group(new List<Tvariable>() { varable })[0];
                //await Task.Run(() =>
                //{
                //    result.SetErrInfo(Write(gp));
                //});
            }
            else
            {
                //Todo 优化为,根据地址,生成一个变量,然后去读取
                result.IsSucceed = false;
                result.Err = "变量名不存在,请检查";
            }
            return result;
        }

        public Result SaveJson(string path = "setting.json")
        {
            // return new Result().SetErrInfo(Auto.SaveAsJson(new Dictionary<string, IDevice>() { { Name, this } }, path));
            return new Result().SetErrInfo(this.SaveAsJson());
        }

        /// <summary>
        ///
        /// </summary>
        /// <param name="loger"></param>
        /// <param name="alarmer"></param>
        /// <param name="dataChange"></param>
        /// <returns></returns>
        public virtual Result Start(LoggerDelegate loger = null, Action<BaseVariable, AlarmEventArgs> alarmer = null, Action<BaseVariable> dataChange = null)
        {
            if (IsRuning)
            {
                loger?.Invoke("设备已经启动(IsRuning=true)");
                return new Result() { IsSucceed = false, Err = $"{Name}正在运行中,请先调用stop方法,停止" };
            }
            if (loger != null)
            {
                Loger = loger;
            }
            if (alarmer != null)
            {
                Alarmer = alarmer;
            }
            if (dataChange != null)
            {
                DataChange = dataChange;
            }
            Cts = new CancellationTokenSource();
            Result result = new Result();
            result.SetErrInfo(Init2());
            Task.Run(() =>
              {
                  if (result.IsSucceed)
                  {
                      if (IsActive)
                      {
                          Loger?.Invoke($"{DateTime.Now}设备初始化成功,正在后台启动中..........");
                          //Cts.Token.Register(() =>
                          //{
                          //    Console.WriteLine($"{DateTime.Now}停止读取{Name}设备的线程成功");
                          //    IsRuning = false;
                          //    Loger?.Invoke($"{DateTime.Now}停止读取{Name}设备的线程成功");
                          //});
                          _ = Task.Run(() =>
                          {
                              IsRuning = true;
                              while (!Cts.IsCancellationRequested)
                              {
                                  if (Connected)
                                  {
                                      foreach (var item in GroupList)
                                      {
                                          if (!Read(item).IsSucceed)
                                          {
                                              ErrorCount++;
                                              DisConnectCount++;
                                              if (ErrorCount > MaxErrorCount)
                                              {
                                                  EventDisConnect?.Invoke(Name);
                                                  ReConnectCount = 1;
                                                  Connected = false;
                                              }
                                          }
                                      }
                                  }
                                  else
                                  {
                                      if (IsFirstConnect)
                                      {
                                          var res = Open();
                                          Connected = res.IsSucceed;
                                          if (Connected)
                                          {
                                              EventConnect?.Invoke(Name, true);
                                              loger?.Invoke($"{Name}首次连接成功");
                                          }
                                          else
                                          {
                                              Loger?.Invoke($"{Name}首次连接{(Connected ? "成功" : $"失败:{res.Exception}")}", res.Exception, AlarmLevel.DisConnect);
                                          }
                                      }
                                      else
                                      {
                                          Loger?.Invoke($"正在进行第{ReConnectCount++}次重新连接中....", null, AlarmLevel.DisConnect);
                                          Thread.Sleep(ReConnectTime);
                                          Connected = Open().IsSucceed;
                                          if (Connected)
                                          {
                                              EventConnect?.Invoke(Name, false);
                                              Loger?.Invoke($"连接成功(第{DisConnectCount})次");
                                          }
                                      }
                                      ErrorCount = 0;
                                      IsFirstConnect = false;
                                      if (!IsGrouped && Connected)
                                      {
                                          GroupCurrentVarable();
                                          IsGrouped = true;
                                      }
                                  }
                              }
                              IsRuning = false;
                              Connected = false;
                          }, Cts.Token);
                      }
                      else
                      {
                          string info1 = IsActive ? "" : $"{Name} 处于未启用状态,若要启用,请更改设备的IsActive属性;  ";
                          string info2 = IsRuning ? $"{Name} 正在运行,请先调用改设备的Stop方法,停止设备" : "";
                          result.Err = info1 + info2;
                      }
                  }
                  else
                  {
                      result.IsSucceed = false;
                      result.Err = "启动失败";
                  }
                  return result;
              });
            return result;
        }

        public Result Stop()
        {
            Result result = new Result();
            try
            {
                Cts.Cancel();
                Thread.Sleep(200);//减少因为正常读取,我们就停止而产生异常,虽然不影响
                result.SetErrInfo(Close());
                IsGrouped = false;
            }
            catch (Exception ex)
            {
                result.IsSucceed = false;
                result.Err = $"停止读取{Name}设备的线程失败";
                result.Exception = ex;
                Loger?.Invoke($"停止读取{Name}的线程失败:{ex.Message}", ex, AlarmLevel.Error);
                return result;
            }
            return result;
        }

        public virtual Result Write(Group<Tvariable> group)
        {
            Result result = new Result();
            var res = GetWriteCommand(group);
            result.SetErrInfo(SendAndRevice(res));
            return result;
        }

        public virtual async Task<Result> WriteAsync(string name, double value)
        {
            Result result = new Result();
            var res = AllVarable.Where(x => x.Name.Norm() == name.Norm()).ToList();
            if (res.Any())
            {
                var varable = res.First();
                varable.WriteValue = (value - varable.Offset) / varable.Scale;
                var gp = Group(new List<Tvariable>() { varable })[0];
                await Task.Run(() =>
                {
                    result.SetErrInfo(Write(gp));
                });
            }
            else
            {
                result.IsSucceed = false;
                result.Err = "变量名不存在,请检查";
            }
            return result;
        }

        #endregion Public Methods

        #region Protected Methods

        /// <summary>
        /// 参数验证成功后:
        /// 将此设备以及此设备的变量添加到当前系统中
        /// </summary>
        /// <returns></returns>
        protected Result AddToAuto()
        {
            Result result = new Result();
            try
            {
                switch (VariableNameType)
                {
                    case VariableNameType.VarName:
                        foreach (var valable in AllVarable)
                        {
                            if (Auto.AllVarable.ContainsKey((valable.Name).Norm()))
                            {
                                Auto.AllVarable[(valable.Name).Norm()] = valable;
                            }
                            else
                            {
                                Auto.AllVarable.Add((valable.Name).Norm(), valable);
                            }
                            //if (Auto.CurrentValueList.ContainsKey((valable.Name).Norm()))
                            //{
                            //    Auto.CurrentValueList[(valable.Name).Norm()] = "Na";
                            //}
                            //else
                            //{
                            //    Auto.CurrentValueList.Add((valable.Name).Norm(), "Na");
                            //}
                        }
                        break;

                    case VariableNameType.VarAddres:
                        foreach (var valable in AllVarable)
                        {
                            if (Auto.AllVarable.ContainsKey((valable.Address).Norm()))
                            {
                                Auto.AllVarable[(valable.Address).Norm()] = valable;
                            }
                            else
                            {
                                Auto.AllVarable.Add((valable.Address).Norm(), valable);
                            }
                            //if (Auto.CurrentValueList.ContainsKey((valable.Address).Norm()))
                            //{
                            //    Auto.CurrentValueList[(valable.Address).Norm()] = "Na";
                            //}
                            //else
                            //{
                            //    Auto.CurrentValueList.Add((valable.Address).Norm(), "Na");
                            //}
                        }
                        break;

                    case VariableNameType.DevNameAndVarName:
                        foreach (var valable in AllVarable)
                        {
                            if (Auto.AllVarable.ContainsKey((Name + "_" + valable.Name).Norm()))
                            {
                                Auto.AllVarable[(Name + "_" + valable.Name).Norm()] = valable;
                            }
                            else
                            {
                                Auto.AllVarable.Add((Name + "_" + valable.Name).Norm(), valable);
                            }
                            //if (Auto.CurrentValueList.ContainsKey((Name + "_" + valable.Name).Norm()))
                            //{
                            //    Auto.CurrentValueList[(Name + "_" + valable.Name).Norm()] = "Na";
                            //}
                            //else
                            //{
                            //    Auto.CurrentValueList.Add((Name + "_" + valable.Name).Norm(), "Na");
                            //}
                        }
                        break;

                    case VariableNameType.DevNameAndVarAddress:
                        foreach (var valable in AllVarable)
                        {
                            if (Auto.AllVarable.ContainsKey((Name + "_" + valable.Address).Norm()))
                            {
                                Auto.AllVarable[(Name + "_" + valable.Address).Norm()] = valable;
                            }
                            else
                            {
                                Auto.AllVarable.Add((Name + "_" + valable.Address).Norm(), valable);
                            }
                            //if (Auto.CurrentValueList.ContainsKey((Name + "_" + valable.Address).Norm()))
                            //{
                            //    Auto.CurrentValueList[(Name + "_" + valable.Address).Norm()] = "Na";
                            //}
                            //else
                            //{
                            //    Auto.CurrentValueList.Add((Name + "_" + valable.Address).Norm(), "Na");
                            //}
                        }
                        break;

                    default:
                        break;
                }

                //if (Auto.AllDevice.ContainsKey(Name.Norm()))
                //{
                //    Auto.AllDevice[Name.Norm()] = this;
                //}
                //else
                //{
                //    Auto.AllDevice.Add(Name.Norm(), this);
                //}
                if (!Auto.AllDevice.Contains(this))
                {
                    Auto.AllDevice.Add(this);
                }
            }
            catch (Exception ex)
            {
                result.IsSucceed = false;
                result.Exception = ex;
                result.Err = ex.Message;
                return result;
            }
            return result;
        }

        /// <summary>
        /// 过时
        /// </summary>
        /// <returns></returns>
        protected virtual Result AutoReadGroup()
        {
            Result result = new Result();
            return result;
        }

        /// <summary>
        /// 过时
        /// </summary>
        /// <returns></returns>
        protected virtual Result CheckAnalyValAddress()
        {
            Result result = new Result();
            return result;
        }

        /// <summary>
        /// 检查设备的各项参数是否设置正确:ip地址,端口号等等
        /// </summary>
        /// <returns></returns>
        protected abstract Result CheckDeviceParameters();

        /// <summary>
        /// 其他验证,比如一些特有的,没有,直接返回True就好
        /// </summary>
        /// <returns></returns>
        protected abstract Result CheckOther();

        /// <summary>
        /// 初始化所有参数
        /// <para>1.设备名变为大写</para>
        /// <para>2.变量名是否重复 TODO 可以配置为变量地址是否重复</para>
        /// <para>3.报警类型是否设定正确</para>
        /// <para>4.等等....</para>
        /// </summary>
        /// <returns></returns>
        protected Result CheckParameters()
        {
            Result result = new Result();

            #region 1.统一设备名

            Name = Name.Norm();

            #endregion 1.统一设备名

            #region 2.检查是否有变量

            if (!AllVarable.Any())
            {
                result.IsSucceed = false;
                result.Err = $"{Name}一个变量都没有";
                return result;
            }

            #endregion 2.检查是否有变量

            #region 3.检查并初始化所有变量

            foreach (var variable in AllVarable)
            {
                //3.统一变量名和变量地址
                variable.Name = variable.Name.Norm();
                variable.Address = variable.Address.Norm();
                //4.解析变量地址
                result.SetErrInfo(variable.AddressAnalysis());
                variable.Bytelength = Common.GetBytelength(variable);

                #region 报警设置检查

                if (variable.AlarmType == AlarmType.None)
                {
                    continue;
                }
                if (variable.AlarmType.HasFlag(AlarmType.None) && variable.AlarmType != AlarmType.None)
                {
                    result.IsSucceed = false;
                    result.Err = Name + "的 " + variable.Name + " 被同时设置为禁止报警和允许报警";
                    continue;
                }
                if (variable.DataType != DataTypeEnum.Bool && (variable.AlarmType.HasFlag(AlarmType.FallingEdge) || variable.AlarmType.HasFlag(AlarmType.RisingEdge)))
                {
                    result.IsSucceed = false;
                    result.Err = Name + "的 " + variable.Name + " 数据类型不是Bool,所以报警类型不能上升沿或者下降沿";
                }
                if (variable.DataType == DataTypeEnum.Bool && (!variable.AlarmType.HasFlag(AlarmType.FallingEdge) && !variable.AlarmType.HasFlag(AlarmType.RisingEdge)))
                {
                    result.IsSucceed = false;
                    result.Err = Name + "的 " + variable + "数据类型是Bool,所以报警类型不能为条件报警";
                }

                #endregion 报警设置检查
            }

            #endregion 3.检查并初始化所有变量

            #region 5.检查变量名和变量地址是否重复

            var res1 = AllVarable.GroupBy(x => x.Name).Where(x => x.Count() > 1).Select(x => x.Key);
            var res2 = AllVarable.GroupBy(x => x.Address).Where(x => x.Count() > 1).Select(x => x.Key);
            if (res1.Any())
            {
                result.IsSucceed = false;
                foreach (var item2 in res1)
                {
                    result.Err = Name + "的 " + item2 + " 变量名重复了";
                }
                return result;
            }
            if (res2.Any())
            {
                result.IsSucceed = false;
                foreach (var item2 in res1)
                {
                    result.Err = Name + "的 " + item2 + " 变量地址重复了";
                }
                return result;
            }

            #endregion 5.检查变量名和变量地址是否重复

            return result;
        }

        /// <summary>
        /// 请调用Open方法,才能保持长连接
        /// <para>连接（如果已经是连接状态会先关闭再打开）,会自动断开</para>
        /// </summary>
        /// <returns></returns>
        [Obsolete("请调用Open方法,才能保持长连接")]
        protected abstract Result Connect();

        /// <summary>
        /// 请调用Close方法
        /// 实现各自关闭连接的方法
        /// </summary>
        /// <returns></returns>
        [Obsolete("推荐调用Close方法,更好")]
        protected abstract Result Disconnect();

        /// <summary>
        /// 根据一个变量组,获取读取报文,如果太大,需要分成多次
        /// <para>需要完整的报文,比如CRC校验等等</para>
        /// </summary>
        /// <param name="group">一个通信组</param>
        /// <returns></returns>
        protected abstract List<byte[]> GetReadCommand(Group<Tvariable> group);

        /// <summary>
        /// 获取写入报文
        /// </summary>
        /// <param name="group"></param>
        /// <returns></returns>
        protected abstract byte[] GetWriteCommand(Group<Tvariable> group);

        /// <summary>
        /// <para>非常重要的方法:将变量按照需求进行分组</para>
        /// <para>todo参数还可以优化,这里写死了list集合,优化为通用的实现可枚举接口的就好</para>
        /// </summary>
        /// <param name="allVariable">变量集合</param>
        /// <returns></returns>
        protected abstract List<Group<Tvariable>> Group(List<Tvariable> allVariable);

        /// <summary>
        /// 发送报文,并获取响应报文:(里面有加锁,所以在多线程的时候,不用发生同时读取写入的情况发生)
        /// <para>真实的数据在result.ResponseData里面</para>
        /// <para>完整的报文在result.Value里面</para>
        /// </summary>
        /// <param name="command">发送命令</param>
        /// <returns></returns>
        protected abstract Result<byte[]> SendAndRevice(byte[] command);

        #endregion Protected Methods

        #region Private Methods

        /// <summary>
        ///
        /// <para>1.调用分组方法,将此设备的所有变量进行分组,就是调用Group()方法,然后赋值给GroupList</para>
        /// <para>2.调用GetReadCommand方法,为每一个组的请求报文赋值</para>
        /// <para>每次分组前需要将<b><see langword="Grouplist"/></b>重新初始化</para>
        /// <a href="http://www.baidu.com">adf</a>
        /// <a href="./nlog.config">怎么跳转本地文件呢?</a>
        /// </summary>
        /// <returns></returns>
        private Result GroupCurrentVarable()
        {
            Result result = new Result();
            GroupList = Group(AllVarable);
            foreach (Group<Tvariable> item in GroupList)
            {
                item.Requst = GetReadCommand(item);//自认为很不错的优化
            }
            return result;
        }

        #endregion Private Methods

    }
}